#import "EventListViewer.h"

// Singleton instance of EventListViewer
static EventListViewer* sharedEventListViewer = nil;

/**
 * An EventListViewer is an object representing the view that 
 * displays a list of events with partial headings and descriptions.
 *
 * An EventViewerDelegate must be set to respond to events from
 * within the inner event viewer.
 *
 * Conforms to the EventViewerDelegate protocol.
 *
 * @author      James Lin
 * @version     0.8.10
 * @since       0.2.3
 * @see         EventViewerDelegate
 * @see         EventViewer
 */
@implementation EventListViewer

/**
 * Retrieve the shared instance of the event list viewer.
 *
 * @return  the shared instance of EventListViewer
 */
+ (EventListViewer*)sharedEventListViewer {
	@synchronized(self) {
		if (sharedEventListViewer == nil) {
			sharedEventListViewer = [[EventListViewer alloc] init];
		}
		return sharedEventListViewer;
	}
}

/**
 * Allocate the event list viewer.
 *
 * @return  the newly allocated shared instance of EventListViewer
 */
+ (id) alloc {
	@synchronized(self) {
		sharedEventListViewer = [super alloc];
		return sharedEventListViewer;
	}
}

/**
 * Retrieve a copy of the event list viewer.
 *
 * @return  the shared instance of EventListViewer
 */
+ (id) copy {
	@synchronized(self) {
		return sharedEventListViewer;
	}
}

/**
 * Get the delegate handling events from the inner event viewer.
 *
 * @return  the delegate handling events from the inner event viewer
 * @see     EventViewerDelegate
 * @see     EventViewer
 */
- (id<EventViewerDelegate>)delegate {
	return [[EventViewer sharedEventViewer] delegate];
}

/**
 * Set the delegate handling events from the inner event viewer.
 *
 * param theDelegate  the delegate handling events from the inner event viewer
 * @see               EventViewerDelegate
 * @see               EventViewer
 */
- (void)setDelegate:(id<EventViewerDelegate>)theDelegate {
	delegate = theDelegate;
}

/**
 * Display the listing of events in a new view.
 *
 * Pushes this view onto the navigation controller stack of the parent
 * view. Upon tapping the back button, the view is automatically 
 * popped off the top of the navigation stack.
 *
 * @param eventList      the list of events to display
 * @param navController  the navigation controller of the parent view
 */
- (void)displayEventList:(NSArray*)eventList 
		   navController:(UINavigationController*)navController {
	// Create the table of event listings
	eventTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 
																   VIEW_WIDTH, VIEW_HEIGHT) 
												  style:UITableViewStylePlain];
	eventTableView.backgroundColor = [UIColor lightGrayColor];
	eventTableView.separatorColor = [UIColor whiteColor];
	eventTableView.tableFooterView = [[[UIView alloc] 
									   initWithFrame:CGRectMake(0, 0, 1, 60)] autorelease];
	
	self.navigationItem.title = @"Events";
	[eventTableView setRowHeight:EVENT_CELL_HEIGHT];
	[eventTableView setDelegate:self];
	[eventTableView setDataSource:self];
	
	// Populate the table with initial event data
	if (eventInfoList) {
		[eventInfoList release];
	}
	eventInfoList = [[NSMutableArray alloc] initWithArray:eventList];
	[eventTableView reloadData];
	parentNav = navController;
	[parentNav setNavigationBarHidden:NO animated:YES];
	
	// Display the table of event listings
	[self.view addSubview:eventTableView];
	[parentNav pushViewController:self animated:YES];
}

/**
 * Get the number of rows in the table view.
 */
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section {
	return eventInfoList.count;
}

/**
 * Populate a table view cell in the table view with content.
 */
- (UITableViewCell*)tableView:(UITableView*)tableView 
		cellForRowAtIndexPath:(NSIndexPath*)indexPath {
	static NSString* CellIdentifier = @"Cell";
	UITableViewCell* cell = [eventTableView dequeueReusableCellWithIdentifier:CellIdentifier];
	
	if (cell == nil) {
		// Create an empty reusable cell for performance sake
		cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
									   reuseIdentifier:CellIdentifier] autorelease];

		CGRect headingLabelFrame = CGRectMake(HORIZONTAL_PADDING, 5, 
											  VIEW_WIDTH-HORIZONTAL_PADDING*2, 30);
		CGRect descriptionLabelFrame = CGRectMake(HORIZONTAL_PADDING, 30, 
												  VIEW_WIDTH-HORIZONTAL_PADDING*2, 70);
		UILabel* tempLabel;
		
		// Create the label for the event heading
		tempLabel = [[UILabel alloc] initWithFrame:headingLabelFrame];
		tempLabel.tag = 1;
		tempLabel.font = [UIFont boldSystemFontOfSize:12.0];
		tempLabel.highlightedTextColor = [UIColor lightGrayColor];
		tempLabel.numberOfLines = 1;
		[cell.contentView addSubview:tempLabel];
		[tempLabel release];
		
		// Create the label for the event description
		tempLabel = [[UILabel alloc] initWithFrame:descriptionLabelFrame];
		tempLabel.tag = 2;
		tempLabel.font = [UIFont systemFontOfSize:10.0];
		tempLabel.highlightedTextColor = [UIColor lightGrayColor];
		tempLabel.numberOfLines = 0;
		[cell.contentView addSubview:tempLabel];
		[tempLabel release];
		
		// Set the background color of the labels
		UIView* cellBackgroundView = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
		cellBackgroundView.backgroundColor = [UIColor lightGrayColor];
		cell.backgroundView = cellBackgroundView;
		for (UIView* view in cell.contentView.subviews) {
			view.backgroundColor = [UIColor clearColor];
		}
		
		// Set the background color for the cell when selected
		UIView* eventCellView = [[[UIView alloc] init] autorelease];
		eventCellView.backgroundColor = [UIColor darkGrayColor];
		cell.selectedBackgroundView = eventCellView;
	}
	
	// Refresh the label content of the cell
	UILabel* headingLabel = (UILabel*)[cell viewWithTag:1];
	UILabel* descLabel = (UILabel*)[cell viewWithTag:2];
	headingLabel.text = ((SFUEvent*)[eventInfoList objectAtIndex:indexPath.row]).eventHeading;
	descLabel.text = ((SFUEvent*)[eventInfoList objectAtIndex:indexPath.row]).eventDescription;
	
	// Display partial event headings and descriptions if text too long
	if ([headingLabel.text length] > MAX_HEADING_LENGTH) {
		headingLabel.text = [NSString stringWithFormat:@"%@%@", 
							 [headingLabel.text substringToIndex: MAX_HEADING_LENGTH], @"..."];
	}
	if ([descLabel.text length] > MAX_DESCRIPTION_LENGTH) {
		descLabel.text = [NSString stringWithFormat:@"%@%@", 
						  [descLabel.text substringToIndex: MAX_DESCRIPTION_LENGTH], @"..."];
	}
	
	return cell;
}

/**
 * View the information of an event that is selected.
 */
- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
	[tableView deselectRowAtIndexPath:indexPath animated:YES];
	[[EventViewer sharedEventViewer] setDelegate:self];
	[[EventViewer sharedEventViewer] displayEvent:[eventInfoList objectAtIndex:indexPath.row] 
									navController:parentNav];
}

/**
 * Handle a request to bookmark a given event.
 *
 * @param event  the event to bookmark
 * @return       whether request was granted and successful
 * @see          EventViewerDelegate
 */
- (BOOL)eventShouldBookmark:(SFUEvent*)event {
	return [delegate eventShouldBookmark:event];
}

/**
 * Handle a request to delete a given bookmarked event.
 *
 * @param event  the bookmarked event to delete
 * @return       whether request was granted and successful
 * @see          EventViewerDelegate
 */
- (BOOL)eventShouldDelete:(SFUEvent*)event {
	BOOL success = [delegate eventShouldDelete:event];
	if (success) {
		[eventInfoList removeObject:event];
		[eventTableView reloadData];
	}
	if ([eventInfoList count] == 0) {
		[parentNav popViewControllerAnimated:NO];
	}
	return success;
}

/**
 * Handle a request to view the location of a given event.
 *
 * @param event  the event to bookmark
 * @return       whether request was granted and successful
 * @see          EventViewerDelegate
 */
- (void)viewLocationOfEvent:(SFUEvent*)event {
	[delegate viewLocationOfEvent:event];
	[parentNav popViewControllerAnimated:NO];
}

/**
 * Deallocate the event list viewer
 */
- (void)dealloc {
	[eventTableView release];
	[sharedEventListViewer release];
    [super dealloc];
}

@end
